package com.yvan.dsf;

import com.alibaba.dubbo.common.utils.ConfigUtils;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.MonitorConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.google.common.base.Strings;
import com.yvan.dsf.listener.ProtocolDict;
import com.yvan.dsf.tracing.client.DstConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

import java.util.Properties;

@Configuration
@EnableConfigurationProperties(DsfProperties.class)
@ConditionalOnBean(annotation = EnableDsfConfiguration.class)
public class DsfAutoConfiguration implements InitializingBean {

    private static final Logger LOGGER = LoggerFactory.getLogger(DsfAutoConfiguration.class);
    @Value("${spring.application.name}")
    private String applicationName;

    @SuppressWarnings("SpringJavaAutowiringInspection")
    private final DsfProperties properties;
    private final Environment env;

    public DsfAutoConfiguration(DsfProperties properties, Environment env) {
        this.properties = properties;
        this.env = env;

        Properties prop = new Properties();
        String pp = env.getProperty("yvan.dsf.trace.mq_name_srv");
        if (!Strings.isNullOrEmpty(pp)) {
            prop.setProperty(DstConstants.ROCKET_MQ_NAME_SRV_ADD, pp);
        }
        ConfigUtils.setProperties(prop);
    }

    @Bean
    public FilterRegistrationBean registControllerFilter() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new DsfHeadeFilter(applicationName));
        //添加过滤规则.
        filterRegistrationBean.addUrlPatterns("/*");

        //添加不需要忽略的格式信息.
        return filterRegistrationBean;
    }

    @Bean
    @ConditionalOnMissingBean
    public ApplicationConfig dubboApplicationConfig() {
        ApplicationConfig appConfig = new ApplicationConfig();
        if (properties.getApp() == null || properties.getApp().isEmpty()) {
            properties.setApp(env.getProperty("spring.application.name"));
        }
        appConfig.setName(properties.getApp());
        appConfig.setOwner(properties.getOwner());
        return appConfig;
    }

    @Bean
    @ConditionalOnMissingBean
    public ProtocolDict dubboProtocolConfig() {
        ProtocolDict dict = new ProtocolDict();

        ProtocolConfig protocolConfig = new ProtocolConfig();
        protocolConfig.setName("dubbo");
        protocolConfig.setPort(properties.getPort());
        protocolConfig.setThreads(properties.getThreads());
        protocolConfig.setSerialization("jzt");
        dict.setDubboProtocol(protocolConfig);

        return dict;
    }

    @Bean
    @ConditionalOnMissingBean
    public RegistryConfig dubboRegistryConfig() {
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setAddress(properties.getRegistry());
        registryConfig.setGroup(properties.getGroup());
        registryConfig.setCheck(true);
        return registryConfig;
    }

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnProperty(prefix = "spring.dubbo", name = "monitor")
    public MonitorConfig dubboMonitorConfig() {
        MonitorConfig monitorConfig = new MonitorConfig();
        monitorConfig.setAddress(properties.getMonitor());
        return monitorConfig;
    }

    @Bean
    public DsfOperationEndpoint dubboOperationEndpoint() {
        return new DsfOperationEndpoint();
    }

    @Bean
    public DsfHealthIndicator dubboHealthIndicator() {
        return new DsfHealthIndicator();
    }

    @Bean
    public DsfEndpoint dubboEndpoint() {
        return new DsfEndpoint();
    }

    @Bean
    public DsfMetrics dubboConsumerMetrics() {
        return new DsfMetrics();
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        LOGGER.info("dubbo config OK!");
    }
}
